package com.sdkj.dao.base.impl;

import java.io.Serializable;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;

import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.SQLQuery;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.transform.Transformers;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import com.sdkj.Entity.BaseEntity;
import com.sdkj.dao.base.IBaseDao;

/**
 * 
 * @author sdkj
 *
 * @param <T>
 */
@Repository
public class BaseDao<T> implements IBaseDao<T> {

	@Autowired
	private SessionFactory sessionFactory;
	
	protected Session getSession() throws SQLException {
		return sessionFactory.getCurrentSession();
	}
	
	public Serializable save(T o) throws SQLException  {
		if(null!=o){ 
			return this.getSession().save(o);
		}
		return 0; 
	}

	public void delete(T o) throws SQLException {
		if(null!=o){
			this.getSession().delete(o);
		}else{
			throw new RuntimeException("要删除的对象不能为空");
		}
	}

	public void saveOrUpdate(T o) throws SQLException {
		if(null!=o){
			this.getSession().saveOrUpdate(o);
		}else{
			throw new RuntimeException("要操作的对象不能为空");
		}
	}

	public void update(T o) throws SQLException {
		if(null!=o){
			this.getSession().update(o);
		}else{
			throw new RuntimeException("要更改的对象不能为空");
		}
	}

	@SuppressWarnings("unchecked")
	public T findById(Class<?> c, Serializable id) throws SQLException {
		if(null!=id){
			return (T) this.getSession().get(c, id);
		}
		return null;
	}

	public T getByHql(String hql) throws HibernateException, SQLException {
		return this.getByHql(hql, null);
	}

	public T getByHql(String hql, Map<String, Object> params) throws HibernateException, SQLException {
		List<T> l = this.findByHql(hql,params,0,0);
		if (l != null && l.size() > 0) {
			return l.get(0);
		}
		return null;
	}

	public List<T> findByHql(String hql) throws SQLException {
		return this.findByHql(hql, null, 0, 0);
	}

	public List<T> findByHql(String hql, Map<String, Object> params) throws SQLException {
		return this.findByHql(hql, params, 0, 0);
	}
	
	@SuppressWarnings("unchecked")
	public List<T> findByHql(String hql, Map<String, Object> params, int page, int rows) throws SQLException {
		Query query=this.getSession().createQuery(hql);
		this.addParams(query, params);
		if(page!=0&&rows!=0){
			return query.setFirstResult((page - 1) * rows).setMaxResults(rows).list();
		}else{
			return query.list();
		}
	}

	public List<Map<String, ?>> findBySqlToMap(String sql) throws HibernateException, SQLException {
		return this.findBySqlToMap(sql, null, 0, 0);
	}

	public List<Map<String, ?>> findBySqlToMap(String sql, int page, int rows) throws HibernateException, SQLException {
		return this.findBySqlToMap(sql, null, page, rows);
	}

	
	public List<Map<String, ?>> findBySqlToMap(String sql, Map<String, Object> params) throws HibernateException, SQLException {
		return this.findBySqlToMap(sql, params, 0, 0);
	}

	
	@SuppressWarnings("unchecked")
	public List<Map<String, ?>> findBySqlToMap(String sql, Map<String, Object> params, int page, int rows) throws HibernateException, SQLException {
		SQLQuery q = getSession().createSQLQuery(sql);
		this.addParams(q, params);
		if(page!=0&&rows!=0){
			return q.setFirstResult((page - 1) * rows).setMaxResults(rows).setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP).list();
		}else{
			return q.setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP).list();
		}
	}
	
	public List<?> findBySqlToBean(String sql, Map<String, Object> params, int page, int rows,Class<?> clazz) throws HibernateException, SQLException {
		SQLQuery q = getSession().createSQLQuery(sql);
		this.addParams(q, params);
		if(page!=0&&rows!=0){
			return q.setFirstResult((page - 1) * rows).setMaxResults(rows).setResultTransformer(Transformers.aliasToBean(clazz)).list();
		}else{
			return q.setResultTransformer(Transformers.aliasToBean(clazz)).list();
		}
	}
	
	@Override
	public int getCountByHql(String hql) throws SQLException {
		return getCountByHql(hql, null);
	}

	@Override
	public int getCountByHql(String hql, Map<String, Object> params) throws SQLException {
		Query q = getSession().createQuery(hql);
		this.addParams(q, params);
		return Integer.parseInt(q.uniqueResult()+"");
	}

	@Override
	public int executeHql(String hql) throws SQLException {
		Query q = getSession().createQuery(hql);
		return q.executeUpdate();
	}

	@Override
	public int executeHql(String hql, Map<String, Object> params) throws SQLException {
		Query q = getSession().createQuery(hql);
		this.addParams(q, params);
		return q.executeUpdate();
	}
	
	public int getCountBySql(String sql) throws SQLException {
		return Integer.parseInt(this.getSession().createSQLQuery(sql).uniqueResult()+"");
	}

	public int getCountBySql(String sql, Map<String,Object> params) throws SQLException {
		SQLQuery query=this.getSession().createSQLQuery(sql);
		this.addParams(query, params);
		return (Integer) query.uniqueResult();
	}

	public int executeSql(String sql) throws SQLException {
		return this.executeSql(sql, null);
	}

	public int executeSql(String sql, Map<String, Object> params) throws SQLException {
		SQLQuery query=this.getSession().createSQLQuery(sql);
		this.addParams(query, params);
		return query.executeUpdate();
	}
	
	@SuppressWarnings("unchecked")
	public List<T> findToBean(String sql,Map<String,Object>params,int page,int rows,Class<T> clazz) throws HibernateException, SQLException{
		Query q = this.getSession().createSQLQuery(sql).setResultTransformer(Transformers.aliasToBean(clazz)) ;
		this.addParams(q, params);
		if(page!=0&&rows!=0){
			return q.setFirstResult((page - 1) * rows).setMaxResults(rows).list();
		}
		return q.list();
	}
	
	public void saveBatch(List<? extends BaseEntity> list) throws SQLException{
		Session session=getSession();
        for(int i=0;i<list.size();i++){
        	session.save(list.get(i));
            if (i!=0&&i % 300 == 0) {  
                session.flush();  
                session.clear();  
            }  
        }
        session.flush();  
        session.clear();  
	}
	
	//==============  strategy 策略方法 ============//
	
	protected void addParams(Query q,Map<String,Object>params){
		if (params != null && !params.isEmpty()) {
			for (String key : params.keySet()) {
				if (params.get(key) instanceof List) {
					q.setParameterList(key, (List<?>) params.get(key));
				} else if (params.get(key) instanceof String[]) {
					q.setParameterList(key, (String[]) params.get(key));
				} else {
					q.setParameter(key, params.get(key));
				}
			}
		}
	}
	
}
